﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HCSAnalyzer.Classes.Base_Classes.DataStructures;
using HCSAnalyzer.Classes._3D;
using LibPlateAnalysis;
using System.Drawing;
using Kitware.VTK;

namespace HCSAnalyzer.Classes.Base_Classes.Viewers._3D.ComplexObjects
{
    class c3DObjectScatterPoints : cComponent
    {
        public double Radius = 3;
        public bool IsLinked = false;
        public bool DrawAxis = true;
        public int ValueToBeDisplayed = -1;
        public int ValueForSphereRadius = -1;
        public cGlobalInfo GlobalInfo = null;

        List<cListGeometric3DObject> ListObjects = null;
        cListExtendedTable Input;


        public c3DObjectScatterPoints()
        {
            Title = "3D complex objects: Scatter points graph";
            //this.GlobalInfo = GlobalInfo;
        }


        public void SetInputData(cListExtendedTable Input)
        {
            this.Input = Input;
        }

        public cFeedBackMessage Run(c3DNewWorld _3DWorld)
        {

            //if(_3DWorld==null)
            //{
            //    FeedBackMessage.IsSucceed = false;
            //    FeedBackMessage.Message = "3D world not defined, operation aborded.";
            //    return FeedBackMessage;
            //}

            if (this.Input == null)
            {
                FeedBackMessage.IsSucceed = false;
                FeedBackMessage.Message = "No input data table defined.";
                return FeedBackMessage;
            }

            this.ListObjects = new List<cListGeometric3DObject>();// new List<cGeometric3DObject>();

            double MinX = this.Input.Min(0);
            double MaxX = this.Input.Max(0);
            double DeltaX = MaxX - MinX;
            if (DeltaX == 0) DeltaX = 1;

            double MinY = this.Input.Min(1);
            double MaxY = this.Input.Max(1);
            double DeltaY = MaxY - MinY;
            if (DeltaY == 0) DeltaY = 1;

            double MinZ = this.Input.Min(2);
            double MaxZ = this.Input.Max(2);
            double DeltaZ = MaxZ - MinZ;
            if (DeltaZ == 0) DeltaZ = 1;

            double MinRad = 0;
            double MaxRad = 0;
            double DeltaRad=1;
            if ((ValueForSphereRadius > 0) && (ValueForSphereRadius < this.Input.Count))
            {
                MinRad = this.Input[3].Min();
                MaxRad = this.Input[3].Max();

                if(MaxRad!=MinRad)
                    DeltaRad=MaxRad-MinRad;
            }

            for (int CurrentSerie = 0; CurrentSerie < this.Input.Count; CurrentSerie++)
            {
                cExtendedTable CurrentTable = this.Input[CurrentSerie];

                if (CurrentTable.Count == 0) continue;

                cListGeometric3DObject TmpListObjects = new cListGeometric3DObject();
                TmpListObjects.Tag = CurrentTable.Tag;

                for (int IdxPt = 0; IdxPt < CurrentTable[0].Count; IdxPt++)
                {
                    cPoint3D Pt = new cPoint3D((CurrentTable[0][IdxPt] - MinX) / DeltaX, (CurrentTable[1][IdxPt] - MinY) / DeltaY, (CurrentTable[2][IdxPt] - MinZ) / DeltaZ);

                    double Rad = this.Radius;
                    if ((ValueForSphereRadius > 0) && (ValueForSphereRadius < this.Input.Count))
                    {
                        Rad = this.Radius * ((CurrentTable[ValueForSphereRadius][IdxPt] - MinRad)) / DeltaRad;
                    }

                    c3DSphere Sphere = new c3DSphere(Pt, Rad / 200.0);

                    if ((CurrentTable.ListTags != null) && (CurrentTable.ListTags[IdxPt] != null) &&(CurrentTable.ListTags[IdxPt].GetType() == typeof(cWell)))
                    {
                        if (CurrentTable.ListTags[IdxPt].GetType() == typeof(cWell))
                        {
                            Sphere.Colour = ((cWell)(CurrentTable.ListTags[IdxPt])).GetClassType().ColourForDisplay;
                            Sphere.Tag = CurrentTable.ListTags[IdxPt];
                            //Sphere.ParentTag =
                        }
                    }
                    else if (this.GlobalInfo != null)
                    {
                        Sphere.Colour = this.GlobalInfo.ListCellularPhenotypes[CurrentSerie % this.GlobalInfo.ListCellularPhenotypes.Count].ColourForDisplay;
                    }


                    TmpListObjects.AddObject(Sphere);

                    if ((ValueToBeDisplayed > 0) && (ValueToBeDisplayed < CurrentTable.Count))
                    {
                        if (_3DWorld != null)
                            TmpListObjects.Add(new c3DText(_3DWorld, CurrentTable[ValueToBeDisplayed][IdxPt].ToString("N3"), new cPoint3D(Pt.X + 0.02, Pt.Y + 0.02, Pt.Z + 0.02), Color.White, 0.01));
                    }
                }

                

                if (IsLinked)
                {
                    for (int IdxPt = 1; IdxPt < CurrentTable[0].Count; IdxPt++)
                    {
                        cPoint3D Pt1 = new cPoint3D((CurrentTable[0][IdxPt] - MinX) / DeltaX, (CurrentTable[1][IdxPt] - MinY) / DeltaY, (CurrentTable[2][IdxPt] - MinZ) / DeltaZ);
                        cPoint3D Pt0 = new cPoint3D((CurrentTable[0][IdxPt - 1] - MinX) / DeltaX, (CurrentTable[1][IdxPt - 1] - MinY) / DeltaY, (CurrentTable[2][IdxPt - 1] - MinZ) / DeltaZ);

                        c3DLine Line = new c3DLine(Pt0, Pt1);
                        TmpListObjects.AddObject(Line);
                    }
                }


                ListObjects.Add(TmpListObjects);

            }
            
            if (DrawAxis && (this.Input[0].Count>2))
            {
                cListGeometric3DObject TmpListObjects1 = new cListGeometric3DObject();

                c3DArrow XAxis = new c3DArrow(new cPoint3D(0, 0, 0), new cPoint3D(1, 0, 0));
                XAxis.Tag = this.Input[0][0].Tag;
                TmpListObjects1.AddObject(XAxis);

                c3DArrow YAxis = new c3DArrow(new cPoint3D(0, 0, 0), new cPoint3D(0, 1, 0));
                YAxis.Tag = this.Input[0][1].Tag;
                TmpListObjects1.AddObject(YAxis);

                c3DArrow ZAxis = new c3DArrow(new cPoint3D(0, 0, 0), new cPoint3D(0, 0, 1));
                ZAxis.Tag = this.Input[0][2].Tag;
                TmpListObjects1.AddObject(ZAxis);

                if (_3DWorld != null)
                {
                    c3DText TmpText = new c3DText(_3DWorld, this.Input[0][0].Name, new cPoint3D(0.45, -0.04, -0.04), Color.White, 0.02);
                    TmpText.Tag = this.Input[0][0].Tag;
                    TmpListObjects1.AddObject(TmpText);
                    TmpListObjects1.AddObject(new c3DText(_3DWorld, MaxX.ToString("N3"), new cPoint3D(0.92, 0.03, -0.03), Color.DimGray, 0.01));
                    TmpListObjects1.AddObject(new c3DText(_3DWorld, MinX.ToString("N3"), new cPoint3D(0.02, 0.03, -0.03), Color.DimGray, 0.01));

                    TmpText = new c3DText(_3DWorld, this.Input[0][1].Name, new cPoint3D(-0.04, 0.45, -0.04), Color.White, 0.02);
                    TmpText.Tag = this.Input[0][1].Tag;
                    TmpListObjects1.AddObject(TmpText);
                    TmpListObjects1.AddObject(new c3DText(_3DWorld, MaxY.ToString("N3"), new cPoint3D(-0.03, 0.92, -0.03), Color.DimGray, 0.01));
                    TmpListObjects1.AddObject(new c3DText(_3DWorld, MinY.ToString("N3"), new cPoint3D(-0.03, -0.02, 0.03), Color.DimGray, 0.01));

                    TmpText = new c3DText(_3DWorld, this.Input[0][2].Name, new cPoint3D(-0.04, -0.04, 0.45), Color.White, 0.02);
                    TmpText.Tag = this.Input[0][2].Tag;
                    TmpListObjects1.AddObject(TmpText);
                    TmpListObjects1.AddObject(new c3DText(_3DWorld, MaxZ.ToString("N3"), new cPoint3D(-0.03, -0.03, 0.92), Color.DimGray, 0.01));
                    TmpListObjects1.AddObject(new c3DText(_3DWorld, MinZ.ToString("N3"), new cPoint3D(0.03, -0.03, -0.02), Color.DimGray, 0.01));
                }


                ListObjects.Add(TmpListObjects1);

            }
            
        

           // _3DWorld.AddGeometric3DObjects(this.ListObjects);
            
            return base.FeedBackMessage;
        }

        public List<cListGeometric3DObject> GetOutPut()
        {
            return this.ListObjects;
        }

    }
}
